#include "Communicator.h"
#include <pthread.h>

// Thread function to receive data
static void* ReceiveThread(void* param);

// Thread function to receive data
static void* HelloMessageThread(void* param);

// Thread function to receive data
static void* HopReliabilityResendThread(void* param);

pthread_mutex_t g_LockNeighbour 	= PTHREAD_MUTEX_INITIALIZER; // Locks for Neighbour Info
pthread_mutex_t g_LockDataStore 	= PTHREAD_MUTEX_INITIALIZER; // Lock for DataStore

Communicator::Communicator()
{
	nSeqNo		= 0;

	m_vecNeighbourInfo.clear();
	m_vecDataStore.clear();
	m_vecRoutingTable.clear();
}

Communicator::~Communicator()
{
	;
}

bool Communicator::Initialize(NODE_INFO &NodeInfo, vector<NEIGBOUR_INFO> &vecNeighbourInfo, CLogger *pLogger)
{
	m_pLogger = pLogger;
	m_pLogger->log(1,"Initialising Communicator");

	pthread_attr_init(&attrReceiveUDP);
	pthread_attr_init(&attrHelloMessage);
	pthread_attr_init(&attrResendDataStore);

	// create a UDP socket: SOCK_DGRAM
	if ((NodeInfo.Clientsockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
	{
		printf("\nError (Initialize): Creating socket()");
		exit(0);
	}

	// Initialize Neighbor Info
	for(unsigned int i=0 ; i < vecNeighbourInfo.size(); i++)
	{
		m_pLogger->log(1,"AddressOWN[%s] AddressNeig[%s] Port[%d]", NodeInfo.strIP.c_str(), vecNeighbourInfo[i].strIP.c_str(), vecNeighbourInfo[i].nPort);
		if ((h = gethostbyname( vecNeighbourInfo[i].strIP.c_str() )) == NULL)
		{
			cout<<"\nError (Initialize): gethostbyname() of [" << NodeInfo.strIP << "]";
			return false;
		}

		bzero(&NeighAddr, sizeof(NeighAddr));
		NeighAddr.sin_family = AF_INET;
        bcopy((char*)h->h_addr, (char*)&NeighAddr.sin_addr.s_addr, h->h_length);		
		NeighAddr.sin_port = htons(vecNeighbourInfo[i].nPort);
		vecNeighbourInfo[i].NeighSockAddr = NeighAddr;
	}

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(NodeInfo.nPort);

	// bind it to an address
	if (bind(NodeInfo.Clientsockfd, (struct sockaddr *) &servaddr,sizeof(servaddr)) < 0)
	{
		printf("\nError (Initialize): bind()");
		exit(0);
	}

	m_NodeInfo				= NodeInfo;
	m_vecNeighbourInfo		= vecNeighbourInfo;

	return true;
}



bool Communicator::StartCommunicator()
{
	m_pLogger->log(1,"Starting Communicator");
	pthread_create(&tidReceUDP, &attrReceiveUDP, ReceiveThread, this);
	pthread_create(&tidHelloMessage, &attrHelloMessage, HelloMessageThread, this);
	pthread_create(&tidResendDataStore, &attrResendDataStore, HopReliabilityResendThread, this);

	// Send the current information that this router is up to all neighbours
	MESSAGE oMessage;
	DATASTORE oDataStoreInfo;
	oDataStoreInfo.nMessageType = MSG_UPDATE;

	char strMessage[MESSAGE_LENGTH];

	for(unsigned int i = 0; i < m_vecNeighbourInfo.size(); i++)
	{
		oMessage.nHeader			= 0 ;
		oMessage.nSeqNo				= GetNextSeqNo() ;
		oMessage.nSourceID			= m_NodeInfo.nNodeID ;
		oMessage.nDestinationID		= m_vecNeighbourInfo[i].nNodeID ;
		oMessage.nMessageType		= MSG_UPDATE;
		oMessage.nMessageSize		= 1 ;
		oMessage.Data = new char[oMessage.nMessageSize];
		*oMessage.Data = m_NodeInfo.nNodeID;

		EncodeMessage(strMessage,oMessage);

		// Backup to DataStore;
		oDataStoreInfo.nSeqNo 		= oMessage.nSeqNo;
		oDataStoreInfo.ClientInfo	= m_vecNeighbourInfo[i].NeighSockAddr;
		oDataStoreInfo.nNextHop		= m_vecNeighbourInfo[i].nNodeID;
		oDataStoreInfo.nMessageSize = MESSAGE_HEADER_LEN + oMessage.nMessageSize;
		memcpy(oDataStoreInfo.strEncodedMessage,strMessage, MESSAGE_LENGTH);
		BackuptoDataStore(oDataStoreInfo);

		SendUDP(m_NodeInfo.Clientsockfd, strMessage, MESSAGE_HEADER_LEN + oMessage.nMessageSize, m_vecNeighbourInfo[i]);

		// If current node is Gateway sent that info to all
		// other internal routers
		if(m_NodeInfo.bGateway)
		{
			// Check if neighbour is NOT gateway and send GatewayInfo
			if (!m_vecNeighbourInfo[i].bGateway)
				SendGateWayInfoEx(m_vecNeighbourInfo[i].nNodeID);
		}

	}

	return true;
}

bool Communicator::SendUDP(int Clientsockfd, char* data, int nLength, NEIGBOUR_INFO NeighbourInfo)
{
	m_pLogger->log(1,"Sending Message to [%d] Length [%d]", NeighbourInfo.nNodeID, nLength);
	if (sendto(Clientsockfd, data, nLength, 0, (struct sockaddr *) &NeighbourInfo.NeighSockAddr , sizeof(sockaddr)) < 0)
	{
		 cout<<"\nError (SendUDP): sendto() Message:[]"<<data;
		 m_pLogger->log(1,"ERROR: Sending Message to[%d] FAILED!!", NeighbourInfo.nNodeID);
		 m_pLogger->log(1,"ERROR: [%s]", strerror(errno));
		 return false;
	}

	m_pLogger->log(1,"Sending Message to[%d]Success!!", NeighbourInfo.nNodeID);

	return true;
}



static void* ReceiveThread(void* param)
{
	Communicator* pThis = static_cast<Communicator*>(param);
	pThis->m_pLogger->log(1,"Started Receive Thread!!");

	int recvLen = 0;

	while (true)
	{
		recvLen = 0;
		pThis->m_pLogger->log(1,"Waiting for Data");

		if ( (recvLen = recv(pThis->m_NodeInfo.Clientsockfd , pThis->strReceivedData, MESSAGE_LENGTH, 0)) < 0)
		{
			printf("\nError (ReceiveThread): recvfrom()");
			exit(0);
		}
		pThis->ProcessIncomingMessage(pThis->strReceivedData, recvLen);
	}

	pthread_exit(0);
}


// Thread function to receive data
static void* HelloMessageThread(void* param)
{
	Communicator* pThis = static_cast<Communicator*>(param);
	pThis->m_pLogger->log(1,"Started Hello Message Thread!!");

	MESSAGE oMessage;
	oMessage.nHeader 		= 0;
	oMessage.nMessageType	= MSG_HELLO;
	oMessage.nMessageSize	= 0;
	oMessage.nSourceID		= pThis->m_NodeInfo.nNodeID;

	char strMessage[MESSAGE_LENGTH];


	while (true)
	{
		usleep(HELLO_PERIOD);
		//pthread_mutex_lock(&g_LockNeighbour);
		for(unsigned int i = 0; i < pThis->m_vecNeighbourInfo.size(); i++)
		{
			if(pThis->m_vecNeighbourInfo[i].nNodeID > pThis->m_NodeInfo.nNodeID &&
					pThis->m_vecNeighbourInfo[i].bAlive == true)
			{
				//Send Hello Message
				pThis->m_pLogger->log(1,"Sending Hello Message to Node[%d] Count[%d]",
						pThis->m_vecNeighbourInfo[i].nNodeID, pThis->m_vecNeighbourInfo[i].nHelloCount);
				oMessage.nDestinationID = pThis->m_vecNeighbourInfo[i].nNodeID;
				oMessage.nSeqNo 		= pThis->GetNextSeqNo();

				pThis->m_vecNeighbourInfo[i].nHelloCount++;
				pThis->m_pLogger->log(1,"Increasing Hello Message counter of Node[%d] Count[%d]",
							pThis->m_vecNeighbourInfo[i].nNodeID, pThis->m_vecNeighbourInfo[i].nHelloCount);
				if(pThis->m_vecNeighbourInfo[i].nHelloCount == MAX_HELLO_DROP)
				{
					pThis->m_pLogger->log(1,"1.Neighbour [%d] Marked DEAD!!!" ,pThis->m_vecNeighbourInfo[i].nNodeID);
					pThis->m_vecNeighbourInfo[i].bAlive = false;
					pThis->m_vecNeighbourInfo[i].nHelloCount++;
					// Forward Withdraw message to other routers
					pThis->DeleteRoutes(pThis->m_vecNeighbourInfo[i].nNodeID, -1);
				}
				else
				{
					pThis->EncodeMessage(strMessage, oMessage);
					pThis->SendUDP(pThis->m_NodeInfo.Clientsockfd, strMessage , MESSAGE_HEADER_LEN + 0, pThis->m_vecNeighbourInfo[i]);
				}
			}
			else if(pThis->m_vecNeighbourInfo[i].bAlive == true)
			{
				pThis->m_vecNeighbourInfo[i].nHelloCount++;
				pThis->m_pLogger->log(1,"Increasing Hello Message counter of Node[%d] Count[%d]",
						pThis->m_vecNeighbourInfo[i].nNodeID, pThis->m_vecNeighbourInfo[i].nHelloCount);

				if(pThis->m_vecNeighbourInfo[i].nHelloCount == MAX_HELLO_DROP)
				{
					pThis->m_pLogger->log(1,"2.Neighbour [%d] Marked DEAD!!!" ,pThis->m_vecNeighbourInfo[i].nNodeID);
					pThis->m_vecNeighbourInfo[i].bAlive = false;
					pThis->m_vecNeighbourInfo[i].nHelloCount++;

					// Forward Withdraw message to other routers
					pThis->DeleteRoutes(pThis->m_vecNeighbourInfo[i].nNodeID, -1);
				}
			}
		}
		//pthread_mutex_unlock(&g_LockNeighbour);
	}

	pthread_exit(0);
}

void Communicator::DeleteRoutes(int nDeadID, int nMsgSrcID)
{
    bool bForwardMessage = false;
    int nDeadIdArr[100];
    unsigned int nDeadNodeCount = 0;
    int nTempPos;

    int nNewActivePath = -1;
    int nHopCount = 100;

    char strSendMessage[MESSAGE_LENGTH];
    MESSAGE oMessage;
    oMessage.nMessageType = MSG_WITHDRAW;

    DATASTORE oDataStore;
    oDataStore.nMessageType	= MSG_WITHDRAW;

    int nFinalDestination = -1;

    nDeadIdArr[0] = nDeadID;
    nDeadNodeCount++;
    if(nMsgSrcID >= 0)
    {
        nTempPos = GetNeighbourDetails(nMsgSrcID);
        if(nTempPos < 0)
        {
            printf("\r\nError (DeleteRoutes):Neighbor not found. \r\n");
            return;
        }
        if(m_vecNeighbourInfo[nTempPos].bGateway && m_NodeInfo.bGateway )
        {
            int nTempPos2 = GetRoute(nDeadID);
            if(nTempPos2 >=0 )
            {
                if(!m_vecRoutingTable[nTempPos2].bPathFromGateWay)
                {
                    SendFullRoutingTable(nMsgSrcID);
                    return;
                }
                else
                {
                    if(m_vecRoutingTable[nTempPos2].nNextHop != nMsgSrcID)
                    {
                        SendFullRoutingTable(nMsgSrcID);
                        return;
                    }
                }
            }
        }
    }

    for (unsigned int i = 0 ; i < m_vecRoutingTable.size(); i++)
    {
        nFinalDestination = -1;
        nNewActivePath = -1;
        nHopCount = 100;



        // For each message check if the Withdrawn router is there
        // in any of the path
        for(int j = 0; j < m_vecRoutingTable[i].nHopCount; j++)
        {
            if( nDeadID ==  m_vecRoutingTable[i].arrPath[j])
            {
                if(m_vecRoutingTable[i].bActivePath)
                {
                    nFinalDestination = m_vecRoutingTable[i].nFinalDest;
                }

                bForwardMessage = true;

                m_pLogger->log(1,"Deleting route at [%d] FinalDesti[%d]", i, m_vecRoutingTable[i].nFinalDest);
                m_pLogger->log(1,"Starting Size [%d]", m_vecRoutingTable.size());
                //pthread_mutex_lock(&g_LockRoutingTable);
                m_vecRoutingTable.erase(m_vecRoutingTable.begin() + i);
                //printRoutingTable();
                //pthread_mutex_unlock(&g_LockRoutingTable);
                m_pLogger->log(1,"Ending Size [%d]", m_vecRoutingTable.size());
                i--;//Done as current i is deleted so new i will be next position
                break;
            }
        }
        if(nFinalDestination >=0 )
        {
            // Resore any backup path to make it active path
            for (unsigned int j = 0 ; j < m_vecRoutingTable.size(); j++)
            {
                if( nFinalDestination ==  m_vecRoutingTable[j].nFinalDest)
                {
                    if(m_vecRoutingTable[j].nHopCount <  nHopCount)
                    {
                        nNewActivePath = j;
                        nHopCount = m_vecRoutingTable[j].nHopCount;
                    }
                }
            }
            if(nNewActivePath >= 0 )
            {
                // Make that the active path
                m_vecRoutingTable[nNewActivePath].bActivePath = true;
            }
            else
            {
                if(m_NodeInfo.bGateway)
                {
                    if(nFinalDestination != nDeadID)
                    {
                        nDeadIdArr[nDeadNodeCount] = nFinalDestination;
                        nDeadNodeCount++;
                    }

                }
            }
        }
    }
    if(!bForwardMessage)
    {
        return;
    }
    for(unsigned int k = 0, l = 0; k < m_vecNeighbourInfo.size(); k++)
    {
        for(l = 0; l < nDeadNodeCount; l++)
        {
            if(m_vecNeighbourInfo[k].nNodeID == nDeadIdArr[l])
            {
                m_vecNeighbourInfo[k].bAlive = false;
                break;
            }
        }
    }


    //# InterDomain Changes
    for(unsigned int k = 0; k < nDeadNodeCount; k++)
    {
        nDeadID = nDeadIdArr[k];
        m_pLogger->log(1,"Forwarding Route Delete Information!!");
        oMessage.nSourceID = m_NodeInfo.nNodeID;
        for(unsigned int i = 0; i < m_vecNeighbourInfo.size(); i++)
        {
            if((k > 0) && !m_vecNeighbourInfo[i].bGateway)
            {
                continue;
            }
            if(nMsgSrcID >= 0)
            {
                nTempPos = GetNeighbourDetails(nMsgSrcID);
                if(nTempPos < 0)
                {
                    printf("\r\nError (DeleteRoutes):Neighbor not found. \r\n");
                    continue;
                }
                if(m_vecNeighbourInfo[nTempPos].bGateway && m_NodeInfo.bGateway && !m_vecNeighbourInfo[i].bGateway)
                {
                    continue;
                }
            }

            //if(m_vecNeighbourInfo[i].nNodeID == nDeadID)
            if(!m_vecNeighbourInfo[i].bAlive)
                continue; // Don't forward to the router which was dead just now
            if(nMsgSrcID == m_vecNeighbourInfo[i].nNodeID)
            {
                if(!m_NodeInfo.bGateway && m_vecNeighbourInfo[i].bGateway)
                {
                    SendFullRoutingTable(m_vecNeighbourInfo[i].nNodeID);
                }
                continue; // No need of forwarding to the router from which WITHDRAW msg is received.
            }

            oMessage.nDestinationID		= m_vecNeighbourInfo[i].nNodeID;
            oMessage.nSeqNo = GetNextSeqNo();
            oMessage.nMessageSize = 1;
            oMessage.Data = new char[oMessage.nMessageSize];
            *(oMessage.Data) = nDeadID;
            EncodeMessage(strSendMessage, oMessage);

            oDataStore.nSeqNo 		= oMessage.nSeqNo;
            oDataStore.nNextHop		= m_vecNeighbourInfo[i].nNodeID;
            oDataStore.nMessageSize = MESSAGE_HEADER_LEN + oMessage.nMessageSize;
            memcpy(oDataStore.strEncodedMessage,strSendMessage, MESSAGE_LENGTH);
            BackuptoDataStore(oDataStore);
            SendUDP(m_NodeInfo.Clientsockfd, strSendMessage, MESSAGE_HEADER_LEN+oMessage.nMessageSize, m_vecNeighbourInfo[i]);
            if(oMessage.Data)
                delete [] oMessage.Data;

            if(!m_NodeInfo.bGateway && m_vecNeighbourInfo[i].bGateway)
            {
                SendFullRoutingTable(m_vecNeighbourInfo[i].nNodeID);
            }
        }
    }


    m_pLogger->log(1, "Deleted Successful!! VectorSize[%d]", m_vecRoutingTable.size());
    for(unsigned int i = 0; i< m_vecRoutingTable.size() ;i++)
    {
        m_pLogger->log(1, "i = [%d], Final[%d] HopCnt[%d] NextHop[%d], Active[%d], Path[%d]",
                i, m_vecRoutingTable[i].nFinalDest, m_vecRoutingTable[i].nHopCount,
                m_vecRoutingTable[i].nNextHop, m_vecRoutingTable[i].bActivePath?1:0,
                m_vecRoutingTable[i].arrPath[0]);
    }

}

// Thread function to Resend data from DataStore and mark
// routers as dead.
static void* HopReliabilityResendThread(void* param)
{
	Communicator* pThis = static_cast<Communicator*>(param);
	pThis->m_pLogger->log(1,"Started Reliability Re-send Thread!!");

	while (true)
	{
		usleep(RESEND_PERIOD);

		pThis->ReSendFromDataStore();
	}

	pthread_exit(0);

}

void Communicator::ProcessIncomingMessage(char strReceivedData[MESSAGE_LENGTH], int nDataLength)
{
	MESSAGE oMessage;
	DecodeMessage(strReceivedData,oMessage);

	switch (oMessage.nMessageType)
	{
	case	MSG_HELLO:
			HandleHelloMessage(oMessage);
			break;

	case	MSG_HELLO_ACK:
			HandleHelloAckMessage(oMessage);
			break;

	case	MSG_UPDATE:
			HandleUpdateMessageEx(oMessage);
			break;

	case	MSG_UPDATE_ACK:
			HandleUpdateAckMessage(oMessage);
			break;

	case	MSG_WITHDRAW:
			HandleWithdrawMessage(oMessage);
			break;

	case	MSG_WITHDRAW_ACK:
			HandleWithdrawAckMessage(oMessage);
			break;

	case	MSG_DATA:
			HandleDataMessage(oMessage);
			break;

	case	MSG_DATA_ACK:
			HandleDataAckMessage(oMessage);
			break;

	case	MSG_GATEWAY_INFO:
			HandleGatewayInfoMessageEx(oMessage);
			break;

	case	MSG_GATEWAY_INFO_ACK:
			HandleGatewayInfoAckMessage(oMessage);
			break;

	}

}

void Communicator::HandleUpdateMessageEx(MESSAGE oMessage)
{
	m_pLogger->log(1,"Processing Message Type[UPDATE] Source[%d]", oMessage.nSourceID);
	m_pLogger->log(1,"UPDATE MESSAGE SeqNo[%d] Source[%d] Destination[%d] Data[%s]",
			oMessage.nSeqNo,oMessage.nSourceID,oMessage.nDestinationID,oMessage.Data);


	bool bForwardMessage = false;// To check if the message has to be forwarded
	bool bSendGateWayInfo = true;
	int bNewAlive = true;

	int nTempSourceofMessage = oMessage.nSourceID;

 	char strSendMessage[MESSAGE_LENGTH];

 	ROUTE_TABLE	oTableEntry;
 	DATASTORE oDataStore;
 	oDataStore.nMessageType = MSG_UPDATE;

	// Send ACK
	SendACK(oMessage.nSeqNo, MSG_UPDATE_ACK, oMessage.nSourceID);

	//Check if own name is present in Path
	for(int j = 0; j < oMessage.nMessageSize; j++)
	{
		if( *(oMessage.Data+j) == m_NodeInfo.nNodeID )
		{
			// Do nothing and return as message can be discarded (Loop)
			m_pLogger->log(1,"Ignore Message [UPDATE]. Forming Loop");
			return;
		}
	}

	// Set the neighbour active field.
	for( unsigned int i = 0 ; i < m_vecNeighbourInfo.size(); i++)
	{
		if( m_vecNeighbourInfo[i].nNodeID == oMessage.nSourceID)
		{
			m_pLogger->log(1, "Marked Node[%d] as ALIVE!!", oMessage.nSourceID);
			m_vecNeighbourInfo[i].nHelloCount = 0;
			m_vecNeighbourInfo[i].bAlive = true;
		}
	}


	oTableEntry.nFinalDest	= *(oMessage.Data);
	oTableEntry.nNextHop	= *(oMessage.Data + oMessage.nMessageSize - 1);
	oTableEntry.nHopCount 	= oMessage.nMessageSize;
	for(int j = 0; j < oMessage.nMessageSize; j++)
	{
		oTableEntry.arrPath[j] = *(oMessage.Data+j);
	}

	bool bObsoletePath = false;
	unsigned int nCount;

	if(m_vecRoutingTable.size() > 0)
	{
		//Search if same exist in m_vecTable
		for(nCount = 0; nCount < m_vecRoutingTable.size(); nCount++)
		{
			if(oTableEntry.nHopCount != m_vecRoutingTable[nCount].nHopCount)
			{
				continue;
			}
			if(oTableEntry.nFinalDest != m_vecRoutingTable[nCount].nFinalDest)
			{
				continue;
			}
			int j;
			for(j = 0; j < oTableEntry.nHopCount; j++)
			{
				if( oTableEntry.arrPath[j] != m_vecRoutingTable[nCount].arrPath[j] )
				{
					break;
				}
			}
			if(j == oTableEntry.nHopCount)
			{
				bObsoletePath	= true;
			}
		}
	}
	if(bObsoletePath)
		return;



	// Destination is present in the first field of Path - *(oMessage.Data)
	// HopCount is size of data in Message - 'nMessageSize'

	//  : Check if the update message has came from a new router.
	// if so generate and send GATEWAY_INFO MESSAGE IMP: after addding route to routing
	// table ONLY attempt sending.

	// Check if information present in Routing Table
	for (unsigned int i = 0 ; i < m_vecRoutingTable.size(); i++)
	{
		//bSkipMessage = false;
		if( m_vecRoutingTable[i].nFinalDest ==  *(oMessage.Data) )
		{
			bNewAlive 		 = false;	// A the node is not a new one
			bSendGateWayInfo = false;	// as the node is an already known node (No GateWay Info)
			//nPos = i;
			if( m_vecRoutingTable[i].nHopCount > oMessage.nMessageSize)// nMessaege size is the hop count here
			{
				//Check if that was the active route
				if (m_vecRoutingTable[i].bActivePath)
				{
					m_pLogger->log(1,"Point1");
					m_vecRoutingTable[i].bActivePath = false;
					bForwardMessage = true;//??
					oTableEntry.bActivePath = true;
					break;
				}

			}
		}
	}

	if(bNewAlive)
	{
		//As it is a new node this path will be the active path
		int newNodePos = 0;
		newNodePos = GetNeighbourDetails(nTempSourceofMessage);
		if (newNodePos >= 0)
		{
			m_vecNeighbourInfo[newNodePos].bAlive = true; //Added by mathew
		}


		oTableEntry.bActivePath = true;
		bForwardMessage = true;
		m_pLogger->log(1,"Point2: Sending GateWAynfo");
	}
	if(m_NodeInfo.bGateway )
	{
		for(unsigned int k =0; k < m_vecRoutingTable.size(); k++)
		{
			if(!m_vecRoutingTable[k].bActivePath)
			{
				m_vecRoutingTable.erase(m_vecRoutingTable.begin()+k);
				k--;
                //printRoutingTable();
			}
		}
        if( !oTableEntry.bActivePath)
        {
            return;
        }
	}

	bForwardMessage = true;

	// Since this is a new router that came up ## all messages in the routing
	// table has to be send to it.
	if(bNewAlive)
	{
		SendFullRoutingTable(nTempSourceofMessage);
	}

	// To override Interdomian and not to keep inactive paths.
	//if(m_NodeInfo.bGateway && (!oTableEntry.bActivePath))
	//	return;

	//# InterDomain Changes
	int nPosx = GetNeighbourDetails(nTempSourceofMessage);
	if(m_vecNeighbourInfo[nPosx].bGateway && m_NodeInfo.bGateway)
	{
		// Then no need to forward message to any routers
		bForwardMessage = false;
		oTableEntry.bPathFromGateWay = true;
		m_vecRoutingTable.push_back(oTableEntry);
		//printRoutingTable();
	}
	else
	{
		m_vecRoutingTable.push_back(oTableEntry);
		//printRoutingTable();
		SendFullRoutingTable(nTempSourceofMessage); //mathew

	}



	// Send Gateway Info   This message need not be generated on every update
	// filter it to only first update about a node
	if(m_NodeInfo.bGateway && bSendGateWayInfo && !(m_vecNeighbourInfo[nPosx].bGateway))
	{
		SendGateWayInfoEx((int)*(oMessage.Data));
	}

	// Forward to other routers if needed
	if(bForwardMessage)	// Message has to be send to other routers
	{
		m_pLogger->log(1,"Forward Message Type[UPDATE]");
		// Add self data to end of message
		oMessage.nSourceID = m_NodeInfo.nNodeID;
		*(oMessage.Data + oMessage.nMessageSize)	= m_NodeInfo.nNodeID;
		oMessage.nMessageSize++;

		for(unsigned int i = 0; i< m_vecNeighbourInfo.size(); i++)
		{
			if(m_vecNeighbourInfo[i].nNodeID == nTempSourceofMessage)
				continue; // Don't forward to the router which had send this message
			if(m_vecNeighbourInfo[i].bAlive == false)
							continue; // Don't forward to the router which is not alive

			if(!m_NodeInfo.bGateway && m_vecNeighbourInfo[i].bGateway == true)
			{
				if(!oTableEntry.bActivePath)
					continue;
			}


			//if(m_NodeInfo.bGateway && m_vecRoutingTable[i].bPathFromGateWay)
			//	continue;

			if(m_vecNeighbourInfo[i].bGateway && m_NodeInfo.bGateway)
			{
				oMessage.nMessageSize 	= 2;
				*(oMessage.Data+1)		= m_NodeInfo.nNodeID;
			}
			oMessage.nDestinationID		= m_vecNeighbourInfo[i].nNodeID;
			oMessage.nSeqNo = GetNextSeqNo();
			EncodeMessage(strSendMessage, oMessage);

		 	oDataStore.nSeqNo 		=	oMessage.nSeqNo;
		 	oDataStore.nNextHop		= m_vecNeighbourInfo[i].nNodeID;
		 	oDataStore.nMessageSize = MESSAGE_HEADER_LEN + oMessage.nMessageSize;
		 	memcpy(oDataStore.strEncodedMessage,strSendMessage, MESSAGE_LENGTH);
			BackuptoDataStore(oDataStore);
			SendUDP(m_NodeInfo.Clientsockfd, strSendMessage, MESSAGE_HEADER_LEN+oMessage.nMessageSize, m_vecNeighbourInfo[i]);
		}
	}
	else

	if(m_vecNeighbourInfo[nPosx].bGateway && m_NodeInfo.bGateway)
	{
		//Special Case Forward all routing information in the routing table with hop = 2
		//and next jump = present
		for(unsigned int k = 0; k < m_vecNeighbourInfo.size(); k++)
		{
			oMessage.nSeqNo = GetNextSeqNo();
			oMessage.nSourceID = m_NodeInfo.nNodeID;
			if (!m_vecNeighbourInfo[k].bGateway)
			{
				continue;
			}
			if(m_vecNeighbourInfo[k].nNodeID == nTempSourceofMessage)
			{
				//continue;
			}
			if(m_vecNeighbourInfo[k].bAlive == false)
		    {
                continue; // Don't forward to the router which is not alive
            }
			oMessage.nDestinationID = m_vecNeighbourInfo[k].nNodeID;
			oMessage.nMessageType = MSG_UPDATE;
			for (unsigned int i = 0; i < m_vecRoutingTable.size(); i++)
			{
				if (m_vecRoutingTable[i].bPathFromGateWay)
				{
					oMessage.Data =	new char[m_vecRoutingTable[i].nHopCount + 1];
					for (int j = 0; j < m_vecRoutingTable[i].nHopCount; j++)
					{
						*(oMessage.Data + j) = m_vecRoutingTable[i].arrPath[j];
					}
					*(oMessage.Data + m_vecRoutingTable[i].nHopCount) =
							m_NodeInfo.nNodeID;
					oMessage.nMessageSize = m_vecRoutingTable[i].nHopCount + 1;
				}
				else
				{
					oMessage.Data = new char[2];
					*(oMessage.Data) = m_vecRoutingTable[i].nFinalDest;
					*(oMessage.Data + 1) = m_NodeInfo.nNodeID;
					oMessage.nMessageSize = 2;

				}

				EncodeMessage(strSendMessage, oMessage);

				oDataStore.nSeqNo = oMessage.nSeqNo;
				oDataStore.nNextHop = m_vecNeighbourInfo[k].nNodeID;
				oDataStore.nMessageSize = MESSAGE_HEADER_LEN + oMessage.nMessageSize;
				memcpy(oDataStore.strEncodedMessage, strSendMessage,MESSAGE_LENGTH);
				BackuptoDataStore(oDataStore);
				SendUDP(m_NodeInfo.Clientsockfd, strSendMessage,
						MESSAGE_HEADER_LEN + oMessage.nMessageSize,
						m_vecNeighbourInfo[k]);

				if(oMessage.Data)
					delete [] oMessage.Data;
			}
		}
	}

	for(unsigned int i = 0; i< m_vecRoutingTable.size() ;i++)
	{
		m_pLogger->log(1, "i = [%d], Final[%d] HopCnt[%d] NextHop[%d], Active[%d], Path[%d]",
				i, m_vecRoutingTable[i].nFinalDest, m_vecRoutingTable[i].nHopCount,
				m_vecRoutingTable[i].nNextHop, m_vecRoutingTable[i].bActivePath?1:0,
						m_vecRoutingTable[i].arrPath[0]);
	}
}


void Communicator::SendData(int nDestinationID, char strMessage[DATA_MESSAGE_MAX], int nDataLength)
{

	MESSAGE oMessage;
	DATASTORE oDataStore;
	char strSendMessage[MESSAGE_LENGTH];

	if(nDestinationID == m_NodeInfo.nNodeID)
	{
		printf("\r\nCannot Send message to itself\r\n");
		printf("\r\nData: %s\r\n", oMessage.Data );
		fflush(stdout);
		return;
	}

	oMessage.nSourceID = m_NodeInfo.nNodeID;
	oMessage.nDestinationID = nDestinationID;
	oMessage.nSeqNo = GetNextSeqNo();
	oMessage.nMessageType = MSG_DATA;
	oMessage.nMessageSize = nDataLength+1;
	oMessage.Data = new char [nDataLength+1];
	memcpy(oMessage.Data, strMessage, nDataLength+1);

	EncodeMessage(strSendMessage,oMessage);

	int nPos = GetRoute(nDestinationID);

	if(nPos < 0)
	{
		//forward to gateway
		nPos = GetRoute(m_NodeInfo.nGatewayID);
		if(nPos<0)
		{
			printf("\r\nError (SendData): No route to the Gateway. Message Discarded.\n");
			return;
		}
	}

	int nNeigPos = GetNeighbourDetails(m_vecRoutingTable[nPos].nNextHop);

	if(nNeigPos < 0)
	{
		cout<< "\r\nError (SendData): Unable to find the next hop neighbour to Gateway\n";
		return;
	}


	oDataStore.nMessageSize = nDataLength+1;
	oDataStore.nMessageType = MSG_DATA;
	oDataStore.nNextHop = m_vecRoutingTable[nPos].nNextHop;
	oDataStore.nSeqNo = oMessage.nSeqNo;
	memcpy(oDataStore.strEncodedMessage,strSendMessage, MESSAGE_LENGTH);
	BackuptoDataStore(oDataStore);

	SendUDP(m_NodeInfo.Clientsockfd, strSendMessage, MESSAGE_HEADER_LEN + oMessage.nMessageSize, m_vecNeighbourInfo[nNeigPos]);
	printf("\r\nData forwarded to %d\r\nPath: ", m_vecRoutingTable[nPos].nNextHop);
	for(int i = m_vecRoutingTable[nPos].nHopCount-1; i >= 0; i--)
	{
		printf("%d ", m_vecRoutingTable[nPos].arrPath[i] );
	}
}


void Communicator::SendFullRoutingTable(int nDestinationID)
{
	//  Delete allocations
	MESSAGE oMessage;
	DATASTORE oDataStore;
	char strSendMessage[MESSAGE_LENGTH];


	oDataStore.nMessageType = MSG_UPDATE;
	oDataStore.nNextHop		= nDestinationID;

	oMessage.nDestinationID = nDestinationID;//nDestination is the Source of message
	oMessage.nSourceID = m_NodeInfo.nNodeID;
	oMessage.Data	= new char[15];
	oMessage.nMessageType = MSG_UPDATE;

	int nPos = GetNeighbourDetails(nDestinationID);

	if (nPos < 0)
	{
		m_pLogger->log(1, "ERROR 4");
		return;
	}

	m_pLogger->log(1, "Pass RouteSize[%d]", m_vecRoutingTable.size());

	//Pass Self ID
	oMessage.nSeqNo				= GetNextSeqNo() ;
	oMessage.nMessageSize		= 1 ;
	*(oMessage.Data) = m_NodeInfo.nNodeID;

	EncodeMessage(strSendMessage,oMessage);

	// Backup to DataStore;
	oDataStore.nSeqNo 		= oMessage.nSeqNo;
	//oDataStore.ClientInfo	= m_vecNeighbourInfo[i].NeighSockAddr;
	oDataStore.nNextHop		= nDestinationID;
	oDataStore.nMessageSize = MESSAGE_HEADER_LEN + oMessage.nMessageSize;
	memcpy(oDataStore.strEncodedMessage,strSendMessage, MESSAGE_LENGTH);
	BackuptoDataStore(oDataStore);

	SendUDP(m_NodeInfo.Clientsockfd, strSendMessage, MESSAGE_HEADER_LEN + oMessage.nMessageSize, m_vecNeighbourInfo[nPos]);

	for(int i = 0,nNeighPos = 0; i< m_vecRoutingTable.size(); i++)
	{
		// Check if current is gateway then don't forward the positions marked as bPathFromGateway
		// Change 1
		if(m_NodeInfo.bGateway && m_vecRoutingTable[i].bPathFromGateWay )
		{
			continue;
		}
		nNeighPos = GetNeighbourDetails(nDestinationID);
		if(nNeighPos >= 0)
		{
			if( m_NodeInfo.bGateway && m_vecNeighbourInfo[nNeighPos].bGateway == true)
				continue;
			if(!m_NodeInfo.bGateway && m_vecNeighbourInfo[nNeighPos].bGateway == true)
			{
				if(!m_vecRoutingTable[i].bActivePath)
					continue;
			}
		}


		oMessage.nMessageSize = m_vecRoutingTable[i].nHopCount;
		oMessage.nSeqNo = GetNextSeqNo();
		for(int j = 0; j< m_vecRoutingTable[i].nHopCount; j++)
		{
			*(oMessage.Data+j) = m_vecRoutingTable[i].arrPath[j];
		}
		oMessage.nMessageSize++;//To add self information
		*(oMessage.Data+oMessage.nMessageSize-1)= m_NodeInfo.nNodeID;
		//memcpy(oMessage.Data, m_vecRoutingTable[i].arrPath , oMessage.nMessageSize);
		EncodeMessage(strSendMessage, oMessage);

		oDataStore.nSeqNo = oMessage.nSeqNo;
		oDataStore.nMessageSize = MESSAGE_HEADER_LEN + oMessage.nMessageSize;
		memcpy(oDataStore.strEncodedMessage, strSendMessage, MESSAGE_LENGTH);

		BackuptoDataStore(oDataStore);
		SendUDP(m_NodeInfo.Clientsockfd, strSendMessage, MESSAGE_HEADER_LEN + oMessage.nMessageSize,
				m_vecNeighbourInfo[nPos]);
	}

	if(oMessage.Data)
		delete [] oMessage.Data;

}



void Communicator::HandleWithdrawMessage(MESSAGE oMessage)
{
	m_pLogger->log(1,"Processing Message Type[WITHDRAW]");

	DATASTORE oDataStore;
	oDataStore.nMessageType = MSG_WITHDRAW;

	int nDeadID = *(oMessage.Data);
	int nTempSourceofMessage = oMessage.nSourceID;

	// Send ACK
	SendACK(oMessage.nSeqNo, MSG_WITHDRAW_ACK, oMessage.nSourceID);


	DeleteRoutes(nDeadID, nTempSourceofMessage);

	for(unsigned int i = 0; i< m_vecRoutingTable.size() ;i++)
	{
		m_pLogger->log(1, "i = [%d], Final[%d] HopCnt[%d] NextHop[%d], Active[%d], Path[%d]",
				i, m_vecRoutingTable[i].nFinalDest, m_vecRoutingTable[i].nHopCount,
				m_vecRoutingTable[i].nNextHop, m_vecRoutingTable[i].bActivePath?1:0,
						m_vecRoutingTable[i].arrPath[0]);
	}

}

void Communicator::SendNewActivePath(int nNewActivePath)
{
	char strSendMessage[MESSAGE_LENGTH];

	MESSAGE oMessage;
	oMessage.nMessageType  =  MSG_UPDATE;
	DATASTORE oDataStore;
	oDataStore.nMessageType = MSG_UPDATE;

	for(unsigned int j = 0; j < m_vecNeighbourInfo.size(); j++)
	{
		if(m_vecNeighbourInfo[j].bGateway && m_NodeInfo.bGateway)
		{
			//Special Case Forward all routing information in the routing table with hop = 2
			//and next jump = present
			oMessage.nSeqNo			= GetNextSeqNo();
			oMessage.nSourceID 		= m_NodeInfo.nNodeID;
			oMessage.nDestinationID = m_vecNeighbourInfo[j].nNodeID;
			oMessage.nMessageType	= MSG_UPDATE;
			fflush(stdout);
			for(unsigned int i = 0; i < m_vecRoutingTable.size(); i++)
			{
				if(m_vecRoutingTable[i].bPathFromGateWay)
				{
					oMessage.Data = new char[m_vecRoutingTable[i].nHopCount + 1];
					for(int j = 0; j < m_vecRoutingTable[i].nHopCount; j++)
					{
						*(oMessage.Data+j) = m_vecRoutingTable[i].arrPath[j];
					}
					*(oMessage.Data+m_vecRoutingTable[i].nHopCount) = m_NodeInfo.nNodeID;
					oMessage.nMessageSize	= m_vecRoutingTable[i].nHopCount + 1;
				}
				else
				{
					oMessage.Data = new char[2];
					*(oMessage.Data) = m_vecRoutingTable[i].nFinalDest;
					*(oMessage.Data+1) = m_NodeInfo.nNodeID;
					oMessage.nMessageSize	= 2;

				}

				EncodeMessage(strSendMessage, oMessage);

				oDataStore.nSeqNo 		= oMessage.nSeqNo;
				oDataStore.nNextHop		= m_vecNeighbourInfo[j].nNodeID;
				oDataStore.nMessageSize = MESSAGE_HEADER_LEN + oMessage.nMessageSize;
				memcpy(oDataStore.strEncodedMessage,strSendMessage, MESSAGE_LENGTH);
				BackuptoDataStore(oDataStore);
				SendUDP(m_NodeInfo.Clientsockfd, strSendMessage, MESSAGE_HEADER_LEN+oMessage.nMessageSize, m_vecNeighbourInfo[j]);

			}
			if(oMessage.Data)
				delete [] oMessage.Data;
		}
	}
}

void Communicator::HandleDataMessage(MESSAGE oMessage)
{
	m_pLogger->log(1,"Processing Message Type[DATA]");

	bool bForwardMessage = false;	// To check if the message has to be forwarded

	DATASTORE oDataStore;
	oDataStore.nMessageType = MSG_DATA;

	char strSendMessage[MESSAGE_LENGTH];

	// Send ACK
	SendACK(oMessage.nSeqNo, MSG_DATA_ACK, oMessage.nSourceID);

	printf("\r\nReceived data message.");
	printf("\r\nFrom router: %d.",oMessage.nSourceID);
	printf("\r\nData: %s\r\n", oMessage.Data );
	fflush(stdout);

	if(oMessage.nDestinationID == m_NodeInfo.nNodeID)
	{
		// Data destined for this node. Else have to forward
		int nTempNPos = GetNeighbourDetails(oMessage.nSourceID);
		if(nTempNPos >= 0)
		{
			if(m_vecNeighbourInfo[nTempNPos].nLastDataSeqNo != oMessage.nSeqNo)
			{
				//  Process message
				*(oMessage.Data + oMessage.nMessageSize) = '\0';
				m_pLogger->log(1,"\nData from [%d]:%s", oMessage.nSourceID, oMessage.Data );
				return;
			}
			else
			{
				m_pLogger->log(1,"Skipping DataMessage [Repeated Seq number]" );
				return;
			}
		}
	}
	else
		bForwardMessage = true;



	//Forward Message
	if(bForwardMessage)
	{
		int nRouteID = GetRoute(oMessage.nDestinationID);

		if (nRouteID >= 0)
		{
			// Send thought that route
			int nNeigbhPos = GetNeighbourDetails(m_vecRoutingTable[nRouteID].nNextHop);
			if(nNeigbhPos >= 0)
			{
				bForwardMessage = false;
				//   Check if seq number is same as last seq number
				if(m_vecNeighbourInfo[nNeigbhPos].nLastDataSeqNo == oMessage.nSeqNo)
				{
					m_pLogger->log(1,"Skipping DataMessage [Repeated Seq number]");
					return;
					//break;
				}
				oMessage.nSeqNo = GetNextSeqNo();
				oMessage.nSourceID = m_NodeInfo.nNodeID;
				EncodeMessage(strSendMessage, oMessage);

				oDataStore.nSeqNo 		=	oMessage.nSeqNo;
				oDataStore.nNextHop		= m_vecNeighbourInfo[nNeigbhPos].nNodeID;
				oDataStore.nMessageSize = MESSAGE_HEADER_LEN + oMessage.nMessageSize;
				memcpy(oDataStore.strEncodedMessage,strSendMessage, MESSAGE_LENGTH);
				BackuptoDataStore(oDataStore);
				SendUDP(m_NodeInfo.Clientsockfd, strSendMessage,  MESSAGE_HEADER_LEN+oMessage.nMessageSize, m_vecNeighbourInfo[nNeigbhPos]);
				printf("\r\nMessage forwarded to router: %d.\nPath: ",m_vecNeighbourInfo[nNeigbhPos].nNodeID);
				for(int i = m_vecRoutingTable[nRouteID].nHopCount-1; i >= 0; i--)
				{
					printf("%d ", m_vecRoutingTable[nRouteID].arrPath[i] );
				}
				fflush(stdout);
			}
			else
			{
				printf("\r\nError (HandleDataMessage): Neighbor  not found. Data Message Dropped!!\n");
			}
		}
		else if (nRouteID == -1)
		{

			if(m_NodeInfo.bGateway)
			{
				printf("\r\nError (HandleDataMessage): No route found. Data Message Dropped!!\n");
				/*Current node is gateway...
				 Path to all external routes should have been present.
				 as route to external route not present.
				 Drop the packet */
			}
			else if(m_NodeInfo.nGatewayID >= 0)
			{
				nRouteID = GetRoute(m_NodeInfo.nGatewayID);
				// Send thought that route
				int nNeigbhPos = GetNeighbourDetails(m_vecRoutingTable[nRouteID].nNextHop);
				if(nNeigbhPos >= 0)
				{
					bForwardMessage = false;
					//   Check if seq number is same as last seq number
					if(m_vecNeighbourInfo[nNeigbhPos].nLastDataSeqNo == oMessage.nSeqNo)
					{
						m_pLogger->log(1,"Skipping DataMessage [Repeated Seq number]" );
						return;
					}
					oMessage.nSeqNo = GetNextSeqNo();
					oMessage.nSourceID = m_NodeInfo.nNodeID;
					EncodeMessage(strSendMessage, oMessage);

					oDataStore.nSeqNo 		=	oMessage.nSeqNo;
					oDataStore.nNextHop		= m_vecNeighbourInfo[nNeigbhPos].nNodeID;
					oDataStore.nMessageSize = MESSAGE_HEADER_LEN + oMessage.nMessageSize;
					memcpy(oDataStore.strEncodedMessage,strSendMessage, MESSAGE_LENGTH);
					BackuptoDataStore(oDataStore);
					SendUDP(m_NodeInfo.Clientsockfd, strSendMessage,  MESSAGE_HEADER_LEN+oMessage.nMessageSize,m_vecNeighbourInfo[nNeigbhPos]);
					printf("\r\nMessage forwarded to Gateway. Next hop: %d\nPath: ", m_vecRoutingTable[nRouteID].nNextHop);
					for(int i = m_vecRoutingTable[nRouteID].nHopCount-1; i >= 0; i--)
					{
						printf("%d ", m_vecRoutingTable[nRouteID].arrPath[i] );
					}
					fflush(stdout);
				}
				else
					printf("\r\nError (HandleDataMessage): Neighbor Info not found. Data Message Dropped!!");

			}
			else
				//m_pLogger->log(1,"GateWay Information Not Present");
				printf("\r\nError (HandleDataMessage): GateWay Information Not Present");
		}
	}
}

void Communicator::HandleGatewayInfoMessageEx(MESSAGE oMessage)
{
	m_pLogger->log(1,"Processing Message Type[GATE_WAY]");
	SendACK(oMessage.nSeqNo, MSG_GATEWAY_INFO_ACK, oMessage.nSourceID);

	bool bForwardMessage = false;	// To check if the message has to be forwarded

	DATASTORE oDataStore;
	oDataStore.nMessageType = MSG_GATEWAY_INFO;

	char strSendMessage[MESSAGE_LENGTH];

	if(oMessage.nDestinationID == m_NodeInfo.nNodeID)
	{
		// Data destined for this node. Else have to forward
		m_NodeInfo.nGatewayID = *(oMessage.Data);
	}
	else
	{
		bForwardMessage = true;
	}

	//Forward Message
	if(bForwardMessage)
	{
		int nRouteID = GetRoute(oMessage.nDestinationID);

		if (nRouteID >= 0)
		{
			// Send thought that route
			int nNeigbhPos = GetNeighbourDetails(m_vecRoutingTable[nRouteID].nNextHop);
			if(nNeigbhPos >= 0)
			{
				oMessage.nSeqNo = GetNextSeqNo();
				oMessage.nSourceID = m_NodeInfo.nNodeID;
				EncodeMessage(strSendMessage, oMessage);

				oDataStore.nSeqNo 		=	oMessage.nSeqNo;
				oDataStore.nNextHop		= m_vecNeighbourInfo[nNeigbhPos].nNodeID;
				oDataStore.nMessageSize = MESSAGE_HEADER_LEN + oMessage.nMessageSize;
				memcpy(oDataStore.strEncodedMessage,strSendMessage, MESSAGE_LENGTH);
				BackuptoDataStore(oDataStore);
				SendUDP(m_NodeInfo.Clientsockfd, strSendMessage,  MESSAGE_HEADER_LEN+oMessage.nMessageSize, m_vecNeighbourInfo[nNeigbhPos]);
			}
			else
				printf("Error (HandleGatewayInfoMessageEx): Route Info not found to [%d]. Data Message Dropped!!\n", oMessage.nDestinationID);
		}
		else if (nRouteID == -1)
		{
			printf("Error (HandleGatewayInfoMessageEx): Route Info not found to [%d]. Data Message Dropped!!\n", oMessage.nDestinationID);
		}
	}
	fflush(stdout);
}


void Communicator::HandleHelloMessage(MESSAGE oMessage)
{
	m_pLogger->log(1,"Processing  Message Type[HELLO] Source [%d]", oMessage.nSourceID);

	SendACK(oMessage.nSeqNo, MSG_HELLO_ACK, oMessage.nSourceID);

	// Reset Hello Counter
	int nPos = GetNeighbourDetails(oMessage.nSourceID);
	if(nPos < 0 )
		return;
	//pthread_mutex_lock(&g_LockNeighbour);
	m_vecNeighbourInfo[nPos].nHelloCount = 0;
	//pthread_mutex_unlock(&g_LockNeighbour);


}
void Communicator::HandleHelloAckMessage(MESSAGE oMessage)
{
	m_pLogger->log(1,"Processing  Message Type[HELLO_ACK] Source [%d]", oMessage.nSourceID);
	int nPos = GetNeighbourDetails(oMessage.nSourceID);
	if(nPos < 0 )
		return;
	//pthread_mutex_lock(&g_LockNeighbour);
	m_vecNeighbourInfo[nPos].nHelloCount = 0;
	m_vecNeighbourInfo[nPos].bAlive = true;
	//pthread_mutex_unlock(&g_LockNeighbour);
}

void Communicator::HandleUpdateAckMessage(MESSAGE oMessage)
{
	// Check in data store for corresponding seq number and delete the
	// entry from vector
	m_pLogger->log(1,"Processing  Message Type[UPDATE_ACK] Source [%d]", oMessage.nSourceID);
	m_pLogger->log(1,"SizeOld[%d]", m_vecDataStore.size());
	RemoveFromDataStore(oMessage.nSeqNo);
	m_pLogger->log(1,"SizeNew[%d]", m_vecDataStore.size());
}

void Communicator::HandleWithdrawAckMessage(MESSAGE oMessage)
{
	// Check in data store for corresponding seq number and delete the
	// entry from vector
	m_pLogger->log(1,"Processing  Message Type[WITHDRAW_ACK] Source [%d]", oMessage.nSourceID);
	RemoveFromDataStore(oMessage.nSeqNo);
}

void Communicator::HandleDataAckMessage(MESSAGE oMessage)
{
	// Check in data store for corresponding seq number and delete the
	// entry from vector
	m_pLogger->log(1,"Processing  Message Type[DATA_ACK] Source [%d]", oMessage.nSourceID);
	RemoveFromDataStore(oMessage.nSeqNo);
}

void Communicator::HandleGatewayInfoAckMessage(MESSAGE oMessage)
{
	// Check in data store for corresponding seq number and delete the
	// entry from vector
	m_pLogger->log(1,"Processing  Message Type[GATEWAYINFO_ACK] Source [%d]", oMessage.nSourceID);
	RemoveFromDataStore(oMessage.nSeqNo);
}

void Communicator::SendGateWayInfoEx(int nDestinationID)
{

	if(!m_NodeInfo.bGateway)
			return;

	MESSAGE oMessage;
	DATASTORE oDataStore;
	char strSendMessage[MESSAGE_LENGTH];

	oMessage.nSourceID = m_NodeInfo.nNodeID;
	oMessage.nDestinationID = nDestinationID;
	oMessage.nSeqNo = GetNextSeqNo();
	oMessage.nMessageType = MSG_GATEWAY_INFO;
	oMessage.nMessageSize = 1;
	oMessage.Data = new char[oMessage.nMessageSize];
	*(oMessage.Data) = m_NodeInfo.nNodeID;

	EncodeMessage(strSendMessage,oMessage);

	int nPos = GetRoute(nDestinationID);

	if(nPos < 0)
	{
		m_pLogger->log(1,"\r\nError (SendGateWayInfoEx): No route in table to %d.", nDestinationID);
			return;
	}

	int nNeigPos = GetNeighbourDetails(m_vecRoutingTable[nPos].nNextHop);

	if(nNeigPos < 0)
	{
		m_pLogger->log(1, "\r\nError (SendGateWayInfoEx): Next hop neighbor details not found.");
		return;
	}

	oDataStore.nMessageSize = oMessage.nMessageSize;
	oDataStore.nMessageType = MSG_GATEWAY_INFO;
	oDataStore.nNextHop = m_vecRoutingTable[nPos].nNextHop;
	oDataStore.nSeqNo = oMessage.nSeqNo;
	memcpy(oDataStore.strEncodedMessage,strSendMessage, MESSAGE_LENGTH);
	BackuptoDataStore(oDataStore);

	SendUDP(m_NodeInfo.Clientsockfd, strSendMessage, MESSAGE_HEADER_LEN + oMessage.nMessageSize, m_vecNeighbourInfo[nNeigPos]);


}

void Communicator::SendACK(int nSeqNo, int nAckType, int nDestinationID)
{
	m_pLogger->log(1,"Sending ACK SeqNo[%d] MessageType[%d] Destination[%d]", nSeqNo,nAckType,nDestinationID);
	bool bNeigStatus = true;
	unsigned int nPos;
	MESSAGE oAckMessage;
	oAckMessage.nHeader				= 0 ;
	oAckMessage.nSeqNo				= nSeqNo;
	oAckMessage.nSourceID			= m_NodeInfo.nNodeID ;
	oAckMessage.nDestinationID		= nDestinationID;
	oAckMessage.nMessageType		= nAckType;
	oAckMessage.nMessageSize		= 0 ;
	oAckMessage.Data				= NULL;

	char strMessage[MESSAGE_LENGTH];
	EncodeMessage(strMessage, oAckMessage);

	for(nPos = 0; nPos < m_vecNeighbourInfo.size(); nPos++)
	{
		if(m_vecNeighbourInfo[nPos].nNodeID == nDestinationID)
		{
			bNeigStatus = true;
			break;
		}
		else
			bNeigStatus = false;
	}
	if(bNeigStatus == false)
		printf("\r\nError (SendACK): Destination not found in the neighbor list");
	else
		SendUDP( m_NodeInfo.Clientsockfd, strMessage, MESSAGE_HEADER_LEN , m_vecNeighbourInfo[nPos]);
}



int Communicator::GetRoute(int nDestinationID)
{
	for(unsigned int i = 0; i < m_vecRoutingTable.size(); i++)
	{
		if(nDestinationID == m_vecRoutingTable[i].nFinalDest
				&& m_vecRoutingTable[i].bActivePath)
		{
			return i;
		}
	}
	return -1;
}

void Communicator::BackuptoDataStore(DATASTORE oDataStoreInfo)
{
	pthread_mutex_lock(&g_LockDataStore);
	m_vecDataStore.push_back(oDataStoreInfo);
	pthread_mutex_unlock(&g_LockDataStore);

}

void Communicator::RemoveFromDataStore(unsigned int nSeqNo)
{
	pthread_mutex_lock(&g_LockDataStore);
	for (unsigned int i = 0; i < m_vecDataStore.size(); i++ )
	{
		if(m_vecDataStore[i].nSeqNo == nSeqNo)
		{
			m_vecDataStore.erase(m_vecDataStore.begin() + i);
			pthread_mutex_unlock(&g_LockDataStore);
			return;
		}
	}
	pthread_mutex_unlock(&g_LockDataStore);
}

void Communicator::ReSendFromDataStore()
{
	int nPos;
	for(unsigned int i = 0; i < m_vecDataStore.size(); i++)
	{
		nPos = GetNeighbourDetails(m_vecDataStore[i].nNextHop);
		if(nPos < 0 )
			continue;

		SendUDP(m_NodeInfo.Clientsockfd, m_vecDataStore[i].strEncodedMessage, m_vecDataStore[i].nMessageSize,
				m_vecNeighbourInfo[nPos]);
	}
}


bool Communicator::EncodeMessage(char *strMessage, MESSAGE MessageInfo)
{
	// To do : Return a string with data encoded.
	int nPos = 0;
	char Message[MESSAGE_LENGTH];
	memset(Message, 0, sizeof(Message));
	Message[0] = 0xFE;
	Message[1] = 0xFE;
	Message[2] = 0xEF;
	Message[3] = 0xEF;
	nPos = 4;
	memcpy(&Message[nPos],&MessageInfo.nSeqNo,sizeof(MessageInfo.nSeqNo));
	nPos += sizeof(MessageInfo.nSeqNo);

	memcpy(&Message[nPos],&MessageInfo.nSourceID,sizeof(MessageInfo.nSourceID));
	nPos += sizeof(MessageInfo.nSourceID);

	memcpy(&Message[nPos],&MessageInfo.nDestinationID,sizeof(MessageInfo.nDestinationID));
	nPos += sizeof(MessageInfo.nDestinationID);

	memcpy(&Message[nPos],&MessageInfo.nMessageType,sizeof(MessageInfo.nMessageType));
	nPos += sizeof(MessageInfo.nMessageType);

	memcpy(&Message[nPos],&MessageInfo.nMessageSize,sizeof(MessageInfo.nMessageSize));
	nPos += sizeof(MessageInfo.nMessageSize);

	if(MessageInfo.nMessageSize > 0)
	{
		memcpy(&Message[nPos],MessageInfo.Data,MessageInfo.nMessageSize);
		nPos += (MessageInfo.nMessageSize);
	}

	Message[nPos] = '\0';
	memcpy(strMessage, Message, nPos);
	return true;
}

bool Communicator::DecodeMessage(char* strMessage, MESSAGE& MessageInfo)
{

	int nPos = 0;

	nPos = 4; // Skip header

	memcpy(&MessageInfo.nSeqNo,&strMessage[nPos],sizeof(MessageInfo.nSeqNo));
	nPos += sizeof(MessageInfo.nSeqNo);

	memcpy(&MessageInfo.nSourceID,&strMessage[nPos],sizeof(MessageInfo.nSourceID));
	nPos += sizeof(MessageInfo.nSourceID);

	memcpy(&MessageInfo.nDestinationID,&strMessage[nPos],sizeof(MessageInfo.nDestinationID));
	nPos += sizeof(MessageInfo.nDestinationID);

	memcpy(&MessageInfo.nMessageType,&strMessage[nPos],sizeof(MessageInfo.nMessageType));
	nPos += sizeof(MessageInfo.nMessageType);

	memcpy(&MessageInfo.nMessageSize,&strMessage[nPos],sizeof(MessageInfo.nMessageSize));
	nPos += sizeof(MessageInfo.nMessageSize);


	if(MessageInfo.nMessageSize > 0)
	{
		MessageInfo.Data = new char[MessageInfo.nMessageSize + 1]; //  For update message to add its own path
		memcpy(MessageInfo.Data,&strMessage[nPos],MessageInfo.nMessageSize);
		nPos += sizeof(MessageInfo.nMessageSize);
	}

	return true;
}


int Communicator::GetNeighbourDetails(int nNeighbourID)
{
	NEIGBOUR_INFO oNeighNode;
	pthread_mutex_lock(&g_LockNeighbour);
	for(unsigned int i = 0; i < m_vecNeighbourInfo.size(); i++)
	{
		if(m_vecNeighbourInfo[i].nNodeID == nNeighbourID)
		{
			pthread_mutex_unlock(&g_LockNeighbour);
			return i;
		}
	}
	pthread_mutex_unlock(&g_LockNeighbour);
	return -1;
}


void  Communicator::printRoutingTable()
{
	vector<ROUTE_TABLE> oVecRouteTable;
	GetRoutingTable(oVecRouteTable);
	int nSerialNum = 1;
	printf("\r\nRouting Table\r\n");
	for(unsigned int index = 0; index < oVecRouteTable.size(); index++)
	{
		if(oVecRouteTable[index].bActivePath)
		{
			printf("%2d. ",nSerialNum++);
			printf("Final Destination: %2d ",oVecRouteTable[index].nFinalDest);
			printf("Next Hop: %2d ",oVecRouteTable[index].nNextHop);
			printf("Hop Count: %2d ",oVecRouteTable[index].nHopCount);
			printf("Active: %s ", oVecRouteTable[index].bActivePath?"Y":"N");
			printf("GateWayPath: %s ", oVecRouteTable[index].bPathFromGateWay? "Y":"N");
			printf("Path: ");
			for(int index1 = 0; index1 < oVecRouteTable[index].nHopCount; index1++)
			{
				printf("%2d ",oVecRouteTable[index].arrPath[index1]);
			}
			printf("\r\n");
		}
	}
	for(unsigned int index = 0; index < oVecRouteTable.size(); index++)
	{
		if(!oVecRouteTable[index].bActivePath)
		{
			printf("%2d. ",nSerialNum++);
			printf("Final Destination: %2d ",oVecRouteTable[index].nFinalDest);
			printf("Next Hop: %2d ",oVecRouteTable[index].nNextHop);
			printf("Hop Count: %2d ",oVecRouteTable[index].nHopCount);
			printf("Active: %s ", oVecRouteTable[index].bActivePath?"Y":"N");
			printf("GateWayPath: %s ", oVecRouteTable[index].bPathFromGateWay? "Y":"N");
			printf("Path: ");
			for(int index1 = 0; index1 < oVecRouteTable[index].nHopCount; index1++)
			{
				printf("%2d ",oVecRouteTable[index].arrPath[index1]);
			}
			printf("\r\n");
		}
	}
	printf("\r\n");
	fflush(stdout);
}
